package fantasyfootball;

import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
import java.util.Scanner;

import org.hibernate.Query;
import org.hibernate.classic.Session;

import fantasyfootball.data.entities.FantasyLeague;
import fantasyfootball.data.entities.FantasyManager;
import fantasyfootball.data.entities.FantasyRoster;
import fantasyfootball.data.entities.FantasyTeam;
import fantasyfootball.data.entities.FantasyTransaction;
import fantasyfootball.data.entities.NFLPlayer;
import fantasyfootball.test.HibernateUtil;

/**
 * Class: 605.441 
 * Group: Richard Koretke, Kay Jantharasorn, Israel Rivera.
 * 
 * @author Israel Rivera
 * 
 */
public class FantasyFootball {

	/**
	 * Displays main options and uses helper functions for each task.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		Scanner scan = new Scanner(System.in);
		PrintWriter writer = new PrintWriter(System.out, true);

		mainOptions(scan, writer);
	}

	/**
	 * Allows a FantasyManager to update his or her email address.
	 * 
	 * @param scan
	 * @param writer
	 */
	private static void updateProfile(Scanner scan, PrintWriter writer) {

		Collection<FantasyManager> fantasyManagers = vaildateManager(scan,
				writer);

		for (FantasyManager manager : fantasyManagers) {

			writer.println("Old Email: " + manager.getEmail());
		}

		writer.println("Enter a new Email Address: ");
		String newEmail = scan.next();

		String emailQuery = "UPDATE FantasyManager manager SET manager.email = :email";

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		Query query = session.createQuery(emailQuery);

		query.setString("email", newEmail);

		query.executeUpdate();

		session.getTransaction().commit();

		// Back to Main Options
		writer.println();
		mainOptions(scan, writer);
	}
	
	/**
	 * Shows the Roster of a FantasyManager
	 * 
	 * @param scan
	 * @param writer
	 */
	private static void showRoster(Scanner scan, PrintWriter writer) {

		Collection<FantasyManager> fantasyManagers = vaildateManager(scan,
				writer);

		writer.println("Here is your Roster: ");

		for (FantasyManager manager : fantasyManagers) {

			for (FantasyTeam team : manager.getFantasyTeams()) {
				writer.println("Fantasy Team Name: " + team.getTeamName());

				for (FantasyRoster roster : team.getFantasyRosters()) {
					writer.println(   roster.getNflPlayer().getFirstName() + " "
									+ roster.getNflPlayer().getLastName()
									+ " Position: "
									+ roster.getNflPlayer().getPosition());
				}
			}
		}

		// Back to Main Options
		writer.println();
		mainOptions(scan, writer);
	}
	
	/**
	 * Validates a FantasyManager.
	 * 
	 * @param scan
	 * @param writer
	 * @return Collection<FantasyManager>
	 */
	private static Collection<FantasyManager> vaildateManager(Scanner scan,
			PrintWriter writer) {

		writer.println("Please enter username: ");
		String userName = scan.next();

		String logInQuery = "FROM FantasyManager manager INNER JOIN FETCH manager.fantasyTeams "
				+ "WHERE manager.logonName = " + "'" + userName + "'";

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		Query query = session.createQuery(logInQuery);

		@SuppressWarnings("unchecked")
		List<FantasyManager> fantasyManagers = query.list();

		session.getTransaction().commit();
		//session.close();

		if (fantasyManagers.isEmpty()) {

			writer.println("Incorrect username!");

			// Back to Main Options
			writer.println();
			mainOptions(scan, writer);

		} else {

			return fantasyManagers;
		}

		return null;
	}
	
	/**
	 * Display's main options and calls a given function based on
	 * user input.
	 * 
	 * @param scan
	 * @param writer
	 */
	private static void mainOptions(Scanner scan, PrintWriter writer) {

		String options =  "1. Update Profile "     + "\n"
						+ "2. Update Roster"      + "\n" 
						+ "3. Show Roster"        + "\n" 
						+ "4. Show Transactions"  + "\n" 
						+ "5. Show Standings";

		writer.println("Welcome to Fantasy Football !");
		writer.println("Please select one of the options: ");
		writer.println(options);
		writer.println("Enter number: ");

		int value = scan.nextInt();

		switch (value) {
		case 1:
			updateProfile(scan, writer);
			break;
		case 2:
			updateRoster(scan, writer);
			break;
		case 3:
			showRoster(scan, writer);
			break;
		case 4:
			showTransactions(scan, writer);
			break;
		case 5:
			showStandings(scan, writer);
		}

	}
	
	/**
	 * Allows a FantasyManager to add or remove players from his or her FantasyRoster.
	 * 
	 * @param scan
	 * @param writer
	 */
	private static void updateRoster(Scanner scan, PrintWriter writer) {
		
		Collection<FantasyManager> fantasyManagers = vaildateManager(scan,
				writer);
		
		writer.println("Add or Remove Players from your roster?");
		writer.println("1. ADD");
		writer.println("2. Remove");
		writer.println("Enter number: ");
		int rosterOption = scan.nextInt();
		
		if(rosterOption == 1) {
			Session session = HibernateUtil.getSessionFactory().getCurrentSession();
			session.beginTransaction();
			
			Query query = session.createQuery("SELECT DISTINCT player FROM NFLPlayer player WHERE player.playerID NOT IN (SELECT roster.nflPlayer.playerID FROM FantasyRoster roster)");
			
			@SuppressWarnings("unchecked")
			List<NFLPlayer> nflPlayers = query.list();			
			
			for(NFLPlayer player : nflPlayers) {
				writer.println( player.getPlayerID() + ": "
								+ player.getFirstName() + " " 
								+ player.getLastName()
								+ " Position: " + player.getPosition());
			}
			
			writer.println("Select one of the players listed to add to your roster. ");
			writer.println("Enter number: ");
			int playerIdToAdd = scan.nextInt();
			
			Query query2 = session.createQuery("SELECT DISTINCT player FROM NFLPlayer player WHERE player.playerID = " + playerIdToAdd);
			
			@SuppressWarnings("unchecked")
			List<NFLPlayer> nflPlayerToAdd = query2.list();
			
			FantasyManager[] manager = fantasyManagers.toArray(new FantasyManager[1]);
			FantasyTeam[] fantasyTeam = manager[0].getFantasyTeams().toArray(new FantasyTeam[1]);
			
			// Add new player to Roster
			FantasyRoster roster = new FantasyRoster();
			roster.setFantasyTeam(fantasyTeam[0]);
			roster.setNflPlayer(nflPlayerToAdd.get(0));
			roster.setPosition(nflPlayerToAdd.get(0).getPosition());
			
			// Add new ADD Transaction
			FantasyTransaction transaction = new FantasyTransaction();
			transaction.setFantasyTeam(fantasyTeam[0]);
			transaction.setNflPlayer(nflPlayerToAdd.get(0));
			transaction.setDate(Calendar.getInstance());
			transaction.setTransactionType("ADD");
			
			session.saveOrUpdate(roster);
			session.saveOrUpdate(transaction);
			
			session.getTransaction().commit();
			
			// Back to Main Options
			writer.println();
			mainOptions(scan, writer);
			
		} else if(rosterOption == 2) {
			
			Session session = HibernateUtil.getSessionFactory().openSession();
			session.beginTransaction();
			
			writer.println("Here is your Roster: ");
			
			FantasyTeam fantasyTeam = null;

			for (FantasyManager manager : fantasyManagers) {

				for (FantasyTeam team : manager.getFantasyTeams()) {
					fantasyTeam = team;
					writer.println("Fantasy Team Name: " + team.getTeamName());

					for (FantasyRoster roster : team.getFantasyRosters()) {
						writer.println(  roster.getRosterID() + ": " 
										+ roster.getNflPlayer().getFirstName() + " "
										+ roster.getNflPlayer().getLastName()
										+ " Position: "
										+ roster.getNflPlayer().getPosition());
					}
				}	
			}
			
			writer.println("Select one of the players listed to remove from your roster. ");
			writer.println("Enter number: ");
			int rosterIdToRemove = scan.nextInt();
			
			Query query = session.createQuery("SELECT DISTINCT roster FROM FantasyRoster roster WHERE roster.rosterID = " + rosterIdToRemove);
			
			@SuppressWarnings("unchecked")
			List<FantasyRoster> fantasyRosters = query.list();
			
			// Add new DROP Transaction
			FantasyTransaction transaction = new FantasyTransaction();
			transaction.setFantasyTeam(fantasyTeam);
			transaction.setNflPlayer(fantasyRosters.get(0).getNflPlayer());
			transaction.setDate(Calendar.getInstance());
			transaction.setTransactionType("DROP");
			
			session.saveOrUpdate(transaction);
			session.delete(fantasyRosters.get(0));
			
			session.getTransaction().commit();
			
			// Back to Main Options
			writer.println();
			mainOptions(scan, writer);
		}	
	}
	
	/**
	 * Displays the standings.
	 * 
	 * @param scan
	 * @param writer
	 */
	private static void showStandings(Scanner scan, PrintWriter writer) {

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		Query query = session
				.createQuery("SELECT DISTINCT league FROM FantasyLeague league INNER JOIN FETCH league.fantasyTeams WHERE league.leagueName = 'EN441'");

		@SuppressWarnings("unchecked")
		List<FantasyLeague> leagueList = query.list();

		session.getTransaction().commit();

		for (FantasyLeague league : leagueList) {

			for (FantasyTeam team : league.getFantasyTeams()) {
				System.out.println("Team Name: " + team.getTeamName()
						+ " Standing: " + team.getTotalPoints() + " Wins: "
						+ team.getWins() + " Loses: " + team.getLoses());
			}
		}

		// Back to Main Options
		writer.println();
		mainOptions(scan, writer);
	}
	
	/**
	 * Show's all transactions.
	 * 
	 * @param scan
	 * @param writer
	 */
	private static void showTransactions(Scanner scan, PrintWriter writer) {

		String fantasyTransactionsQuery = "FROM FantasyTransaction";
			
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		Query query = session.createQuery(fantasyTransactionsQuery);

		@SuppressWarnings("unchecked")
		List<FantasyTransaction> fantasyTransactions = query.list();

		session.getTransaction().commit();

		for (FantasyTransaction transaction : fantasyTransactions) {
				writer.println(transaction.getTransactionType() + ": "
						+ "FantasyTeam: " +transaction.getFantasyTeam().getTeamName() + " "
						+ transaction.getNflPlayer().getFirstName() + " "
						+ transaction.getNflPlayer().getLastName() 
						+ " Position: "
						+ transaction.getNflPlayer().getPosition());
		}

		// Back to Main Options
		writer.println();
		mainOptions(scan, writer);
	}

}
